/**
 * 
 */
package javapop.framework.parser.tuple;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javapop.framework.ParseContext;
import javapop.framework.ParseError;
import javapop.framework.ParseInput;
import javapop.framework.ParseResult;
import javapop.framework.Parser;
import javapop.framework.parser.TupleParser;

/**
 * @author Hakim Belhaouari
 *
 */
public class ListTuple extends Parser<Collection<Object>> {

	private TupleParser parser;
	private int cardinality;
	private int size;
	
	/**
	 * 
	 */
	public ListTuple(int cardinality) {
		parser = new TupleParser();
		this.cardinality = cardinality;
		this.size = 0;
	}

	public ListTuple then(Parser silent) {
		parser.addSilent(silent);
		return this;
	}
	
	public ListTuple parser(Parser first) {
		if(size < cardinality) {
			parser.addComponent(first);
			size++;
		}
		else
			throw new IllegalStateException("Wrong cardinality: expected "+cardinality+" got "+size);
		return this;
	}
		
	public ListTuple fatalFrom(int ref) {
		parser.setFatalFrom(ref);
		return this;
	}
	
	/**
	 * @see javapop.framework.Parser#eval(javapop.framework.ParseContext, javapop.framework.ParseInput)
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public ParseResult eval(ParseContext ctx, ParseInput input) {
		ArrayList<Object> al = new ArrayList<Object>();
		ParseResult<List<?>> result = parser.parse(ctx, input);
		if(result.isError()) {
			return (ParseResult) result.asError();
		}
		List<?> results = result.getResult();
		if(results.size()!=cardinality) {
			return (ParseResult) new ParseError("Wrong cardinality: expected "+cardinality+" got "+results.size());
		}
		for(int i=0; i < size;i++) {
			Object o = results.get(i);
			al.add(o);
		}
		return buildResult(al);
	}

	/**
	 * @see javapop.framework.Parser#getDescription()
	 */
	@Override
	public String getDescription() {
		return parser.getDescription();
	}
	
	@Override
	public boolean isMemoized() {
		return false;
	}

}
